import moment from 'moment';
import React, {
  ReactElement,
  useContext,
  useEffect,
  useMemo,
  useState
} from 'react';
import { ActivityIndicator, Image, Text, View } from 'react-native';
import { Message } from '../../../../../../api/class/getMessageList';
import Button from '../../../../../../components/Button';
import { avatar } from '../../../../../../constant/resource';
import { getUserInfo } from '../../../../../../store/user';
import { phonePx } from '../../../../../../util/adapt';
import { CLASS_ROOM_RIGHT_SCALE } from '../../../../constant';
import MsgBox, { DirectType } from '../../../Graph/MsgBox';
import {
  playMessageWithId,
  withDrawMessage,
  stopPlayMessage
} from '../../actions';
import {
  MAX_CAN_WITH_DRAW_TIME,
  MIN_MESSAGE_WIDTH,
  MessageType
} from '../../constant';
import { Store } from '../../reducer';
import PlayVoice, { PlayVoiceType } from '../PlayVoice';
import TextMessage, { TextMessageType } from '../TextMessage';
import styles from './style';

interface MessageProps {
  message: Message;
}

export default ({ message }: MessageProps): ReactElement => {
  const {
    senderId,
    withdraw,
    type,
    isRead,
    messageId,
    canWithDraw,
    sendTime,
    isSending
  } = message;
  const [isCanWithDraw, setIsCanWithDraw] = useState<boolean>(false);

  const { state } = useContext(Store);
  const { assistantInfo } = state;
  const { headUrl, name } = assistantInfo;

  const { userId, headUrl: localHeadUrl } = getUserInfo();
  const isOtherMessage = Number(userId) !== Number(senderId);

  useEffect((): void => {
    if (!isOtherMessage && canWithDraw) {
      setIsCanWithDraw(!!canWithDraw);
    }
  }, [canWithDraw, isOtherMessage]);

  useEffect((): (() => void) => {
    let timer: NodeJS.Timer | null = null;
    const sendUnix = moment(sendTime).unix();
    const currentUnix = moment().unix();
    const currentInterval = currentUnix - sendUnix;
    const leftInterval = MAX_CAN_WITH_DRAW_TIME - currentInterval;
    if (isCanWithDraw && leftInterval > 0) {
      timer = setTimeout((): void => {
        setIsCanWithDraw(false);
      }, leftInterval * 1000);
    }

    return (): void => {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
    };
  }, [isCanWithDraw, sendTime]);

  return useMemo((): ReactElement => {
    if (type === MessageType.Event) return <View />;

    if (isSending) {
      return (
        <View style={[styles.container, styles.own]}>
          <ActivityIndicator animating size="small" style={styles.loading} />
          <MsgBox
            style={styles.ownVoice}
            fillColor="rgba(247, 215, 106, 1)"
            directType={DirectType.Right}
            dia={phonePx(4) * CLASS_ROOM_RIGHT_SCALE}
            surfaceWidth={MIN_MESSAGE_WIDTH}
          />
          <Image
            style={styles.ownHead}
            source={localHeadUrl ? { uri: localHeadUrl } : avatar}
          />
        </View>
      );
    }

    if (withdraw) {
      return (
        <Text style={styles.haveWithDraw}>
          {isOtherMessage ? `"${name}" 撤回了一条消息` : '你撤回了一条消息'}
        </Text>
      );
    }

    if (isOtherMessage) {
      return (
        <View style={[styles.container, styles.other]}>
          <Image
            style={styles.head}
            source={headUrl ? { uri: headUrl } : avatar}
          />
          {type === MessageType.Text ? (
            <TextMessage
              textMessageType={TextMessageType.Other}
              message={message}
              style={styles.voice}
            />
          ) : (
            <PlayVoice
              playVoiceType={PlayVoiceType.Other}
              message={message}
              style={styles.voice}
              play={(): void => {
                playMessageWithId(message);
              }}
              stop={(): void => {
                stopPlayMessage();
              }}
            />
          )}
          {!isRead && <View style={styles.unRead} />}
        </View>
      );
    }

    return (
      <View style={[styles.container, styles.own]}>
        {!withdraw && isCanWithDraw && (
          <Button
            hitSlop={{ left: 20, top: 20, right: 20, bottom: 20 }}
            text="撤回"
            textStyle={styles.withDrawDesc}
            style={styles.withDraw}
            onPress={(): void => {
              withDrawMessage(messageId);
            }}
          />
        )}
        <PlayVoice
          playVoiceType={PlayVoiceType.Own}
          message={message}
          style={styles.ownVoice}
          play={(): void => {
            playMessageWithId(message);
          }}
          stop={(): void => {
            stopPlayMessage();
          }}
        />
        <Image
          style={styles.ownHead}
          source={localHeadUrl ? { uri: localHeadUrl } : avatar}
        />
      </View>
    );
  }, [
    headUrl,
    isCanWithDraw,
    isOtherMessage,
    isRead,
    isSending,
    localHeadUrl,
    message,
    messageId,
    name,
    type,
    withdraw
  ]);
};
